import {TokenService, TokenStatus} from "@/login/TokenService";
import {MicroBaseEntryMainConfig, NavigatorRouteType} from "plain-micro-application";
import {nav} from "@/micro/nav/nav";
import {defer} from "plain-design-composition";
import {createUserService} from "@/login/UserService";
import {delay} from 'plain-utils/utils/delay'
import {ManagerMenuService} from "@/application/manager/ManagerMenuService";

/**
 * 登录接口返回的数据对象类型
 * @author  韦胜健
 * @date    2021/2/22 16:06
 */
interface LoginRespDTO {
    code: number,
    data: {
        expires: number
        token: string
        user: {
            name: string
            username: string
        },
    },
    error: string | undefined,
}

export const LoginService = {
    /**
     * LoginService 初始化函数，在 micro.init.ts 中初始化
     * @author  韦胜健
     * @date    2021/2/23 9:58
     */
    init: (
        {
            getLoginRender,
            render,
            token,
            mainConfig,
        }: {
            getLoginRender: () => Promise<() => JSX.Element>,                   // 获取渲染登录页面的渲染函数
            render: {
                clear: () => void,                                              // 销毁主页
                home: () => void,                                               // 调用使得应用渲染系统主页面(crm-home, dms-home)
                login: () => void,                                              // 调用使得应用渲染private页面(检查登录，全屏只渲染页面，请求中带token)
            },
            token: TokenService,                                                // token管理服务
            mainConfig: MicroBaseEntryMainConfig,                               // 初始化的时候，由main主应用传递的mainConfig参数
        }) => {
        LoginService.config = {getLoginRender, mainConfig,}
        LoginService.render = render
        LoginService.token = token
    },
    /**
     * 登录请求
     * @author  韦胜健
     * @date    2021/2/18 17:25
     */
    loginRequest: async ({url, loginData, onSuccess, onError,}: {
        url: string,
        loginData: { username: string, password: string },
        onSuccess: (dto: LoginRespDTO, response: any) => void,
        onError: (e: Error | string) => void,
    }) => {
        /*
        *  模拟登陆，只有用户名密码为 admin/888888 才能登陆
        */
        const {username, password} = loginData
        if (username !== 'admin') {return onError('用户名为admin')}
        if (password !== '888888') {return onError('密码为888888')}
        await delay(2000)
        const resp = {
            dto: {
                code: 200,
                data: {
                    expires: 2 * 60 * 1000 * 1000,
                    token: `random_token_${Date.now()}`,
                    user: {
                        username,
                        name: '管理员',
                    },
                },
                error: undefined,
            },
        }
        /*
        *  登陆完毕之后更新token以及过期时间
        */
        LoginService.token.update(resp.dto.data.user.username, resp.dto.data.expires, resp.dto.data.token)
        return onSuccess(resp.dto, resp)
    },
    login: (() => {
        /*这个变量充当一个类型的作用*/
        const loginResolveData = {} as { dto: LoginRespDTO, resp: any }

        return Object.assign(async () => {
            /*清理tab信息*/
            nav.tab.clear()
            LoginService.render.login()
            const dfd = defer<typeof loginResolveData>()
            /*登录页面登录成功之后需要调用这个 login.resolve*/
            LoginService.login.resolve = (data: typeof loginResolveData) => dfd.resolve(data)
            return dfd.promise
        }, {
            resolve: {} as ((data: typeof loginResolveData) => void)
        })
    })(),
    logout: async () => {
        LoginService.token.clear()                          // 清理token
        LoginService.user.clear()                           // 清理用户信息
        nav.tab.clear()                                     // 清空所有的tab
        // todo 清空菜单数据
        ManagerMenuService.clear()                         // 清空菜单数据
        await LoginService.login()

        /*login,home,default,page都需要重新加载用户信息*/
        await Promise.all([
            LoginService.user.init(),
            (async () => {
                if (nav.initialState.config.routeType === NavigatorRouteType.home) {
                    /*login、home、default需要重新加载菜单信息*/
                    // todo 重新加载菜单信息
                    await ManagerMenuService.init()
                }
            })(),
        ])

        await LoginService.render.home()
    },
    checkLogin: async () => {
        if (LoginService.token.getStatus() !== TokenStatus.signed) {
            await LoginService.login()
        }
    },
    /**
     * user管理服务
     * @author  韦胜健
     * @date    2021/2/23 10:29
     */
    user: createUserService(),
    /*---------------------------------------在init函数中初始化的变量-------------------------------------------*/
    /**
     * LoginService内部状态
     * @author  韦胜健
     * @date    2021/2/23 9:57
     */
    config: {} as {
        getLoginRender: () => Promise<() => JSX.Element>,               // 获取渲染登录页面的渲染函数
        mainConfig: MicroBaseEntryMainConfig,                           // main主应用传递的mainConfig参数
    },
    /**
     * 调用LoginService渲染主页面
     * @author  韦胜健
     * @date    2021/2/23 9:57
     */
    render: {} as {
        clear: () => void,                                              // 销毁主页
        home: () => void,                                               // 调用使得应用渲染系统主页面(crm-home, dms-home)
        login: () => void,                                              // 调用使得应用渲染private页面(检查登录，全屏只渲染页面，请求中带token)
    },
    /**
     * token管理服务
     * @author  韦胜健
     * @date    2021/2/23 10:29
     */
    token: {} as TokenService,
}